/* glcd.c

Copyright (C) Alex S. (mailto: md5sum@alexsp.ru)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details
http://www.gnu.org/licenses/gpl-2.0.html.

You should have received a copy of the GNU General Public License
along with this program in the file gpl-2.0.txt;
if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "glcd.h"
#include "fonts.h"

#define nop()  __asm__ __volatile__("nop\r\nnop\r\nnop\r\nnop")
#define GLCD_A	GLCD_contr &=~GLCD_CSA;GLCD_contr|=GLCD_CSB
#define GLCD_B	GLCD_contr &=~GLCD_CSB;GLCD_contr|=GLCD_CSA

#define START_TIME 87 /*Начальная позиция вывода часов*/

#if HUMIDITY>0
#define TIME_OFFSET 0 /*Смещение часов вниз - не более 5!*/
#else
#define TIME_OFFSET 5
#endif

#define START_DELTA_P 47 /*Позиция отклонения давления*/
#define START_TEMP 0
#define TEMP_OFFSET 2
#define DELTA_T_OFFSET 3
#define START_RH 86
#define RH_OFFSET 5

static uint8_t lcd_x=0,lcd_y=0;
static void GLCD_put_command(const uint8_t data);
void GLCD_xy(const uint8_t x, const uint8_t y);
static void print_delta_t(int8_t t1max, int8_t t1min, int8_t t2max, int8_t t2min);
static void print_delta_press(uint16_t p1,uint16_t p2);
static void plot_press(uint16_t press);
uint8_t display_mode=DISPLAY_PRESSURE;

inline static uint8_t GLCD_get_status(){
	uint8_t tmp;
	GLCD_read();
	GLCD_contr&=~GLCD_RS;
	GLCD_DDRx=0;
	GLCD_PORTx=0xff;
	GLCD_contr|=GLCD_E;
	nop();
	tmp=GLCD_PINx;
	GLCD_contr&=~GLCD_E;
	return tmp&GLCD_busy;
}

static void GLCD_select_cs() {
	if (lcd_x==0x40) {
		GLCD_B;
		GLCD_put_command(0x40);
		GLCD_put_command(0xb8|(lcd_y&0x07));
	}
	if (lcd_x==0x80) {
		lcd_x=0;
		if (lcd_y<7) lcd_y++; else lcd_y=0;
	}
	if (lcd_x==0) {
		GLCD_A;
		GLCD_put_command(0x40);
		GLCD_put_command(0xb8|(lcd_y&0x07));
	}

}

uint8_t GLCD_get_data(){
	uint8_t tmp;

	while (GLCD_get_status());
	GLCD_read();
	GLCD_contr|=GLCD_RS;
	GLCD_DDRx=0;
	GLCD_PORTx=0xff;
	GLCD_contr|=GLCD_E;
	nop();
	tmp=GLCD_PINx;
	GLCD_contr&=~GLCD_E;
	lcd_x++;
	GLCD_select_cs();
	return tmp;
}


void GLCD_put_data(const uint8_t data){
	while (GLCD_get_status());
	GLCD_write();
	GLCD_contr|=GLCD_RS;
	GLCD_PORTx = data;
	GLCD_DDRx=0xff;
	nop();
	GLCD_contr|=GLCD_E;
	nop();
	GLCD_contr&=~GLCD_E;
	lcd_x++;
	GLCD_select_cs();
}

static void GLCD_put_command(const uint8_t data){
	while (GLCD_get_status());
	GLCD_write();
	GLCD_contr&=~GLCD_RS;
	GLCD_PORTx = data;
	GLCD_DDRx=0xff;
	nop();
	GLCD_contr|=GLCD_E;
	nop();
	GLCD_contr&=~GLCD_E;
}

void GLCD_clear() {
	uint16_t i;
	GLCD_xy(0,0);
	for (i=0;i<128*8;i++) {
		GLCD_put_data(0x00);
	}
}

void GLCD_init() {
	GLCD_contr&=~GLCD_RST;
	GLCD_contr&=~GLCD_E;
	GLCD_contr_ddr|=(GLCD_CSA|GLCD_CSB|GLCD_RS|GLCD_RW|GLCD_E|GLCD_RST);
	GLCD_PORTx=0;
	GLCD_DDRx=0x0;
	GLCD_contr|=GLCD_CSA|GLCD_CSB|GLCD_RW;
	GLCD_contr|=GLCD_RST;
	nop();
	GLCD_B;
	GLCD_put_command(0xc0);
	GLCD_put_command(0x3f);
	GLCD_A;
	GLCD_put_command(0xc0);
	GLCD_put_command(0x3f);
	GLCD_clear();
	GLCD_xy(0,0);
}

/*from left(0),top(0) to right(127),bottom(7)*/
void GLCD_xy(const uint8_t x, const uint8_t y) {
	lcd_y=y;
	lcd_x=x;
	if (lcd_x<0x40) {GLCD_A;} else {GLCD_B;}
	GLCD_put_command(0x40|(lcd_x&0x3f));
	GLCD_put_command(0xb8|(lcd_y&0x07));
}

void GLCD_print_mem(const prog_uint8_t *c,const uint8_t len, const uint8_t offset, const uint8_t mask){
	uint8_t tmp,x,y;
	uint16_t a;
	uint8_t i;
	prog_uint8_t *p;
	p=(prog_uint8_t *)c;
	for (i=0;i<len;i++) {
		tmp=pgm_read_byte(p++);
		x=lcd_x;
		y=lcd_y;
		GLCD_xy(x,y);
		GLCD_get_data();
		GLCD_xy(x,y);
		a=(uint16_t)GLCD_get_data();
		if (y<7) {
			GLCD_xy(x,y+1);
			GLCD_get_data();
			GLCD_xy(x,y+1);
			a|=(((uint16_t)GLCD_get_data())<<8);
		}
		a&=~(((uint16_t)mask)<<offset);
		a|=(((uint16_t)tmp&mask)<<offset);
		GLCD_xy(x,y);
		GLCD_put_data((uint8_t)(a&0xff));
		if (y<7) {
			GLCD_xy(x,y+1);
			GLCD_put_data((uint8_t)((a>>8)&0xff));
		}
		GLCD_xy(x+1,y);
	}
}

void GLCD_print_5x8(const uint8_t c, const uint8_t offset, uint8_t space) {
	GLCD_print_mem((const prog_uint8_t *)&font_5x8[c][0],5,offset,0xff);
	if (space) GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,offset,0xff);
}

void GLCD_print_3x5(const uint8_t c, const uint8_t offset, uint8_t space) {
	GLCD_print_mem((const prog_uint8_t *)&font_3x5[c][0],3,offset,0x1f);
	if (space) GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,offset,0x1f);
}

void GLCD_print_10x16(const uint8_t c, const uint8_t offset, uint8_t space) {
	uint8_t x=lcd_x;
	uint8_t y=lcd_y;
	GLCD_print_mem((const prog_uint8_t *)&font_10x16[c][0][0],10,offset,0xff);
	if (space) GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,offset,0xff);
	GLCD_xy(x,y+1);
	GLCD_print_mem((const prog_uint8_t *)&font_10x16[c][1][0],10,offset,0x7f);
	if (space) GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,offset,0x7f);
	if (space) GLCD_xy(x+11,y); else GLCD_xy(x+10,y);
}

void GLCD_print_12x16(const uint8_t c, const uint8_t offset, uint8_t space) {
	uint8_t x=lcd_x;
	uint8_t y=lcd_y;
	GLCD_print_mem((const prog_uint8_t *)&font_12x16[c][0][0],11,offset,0xff);
	if (space) GLCD_print_mem((const prog_uint8_t *)&font_12x16[c][0][11],1,offset,0xff);
	GLCD_xy(x,y+1);
	GLCD_print_mem((const prog_uint8_t *)&font_12x16[c][1][0],12,offset,0x7f);
	if (space) GLCD_print_mem((const prog_uint8_t *)&font_12x16[c][1][11],1,offset,0xff);
	if (space) GLCD_xy(x+12,y); else GLCD_xy(x+11,y);
}
void GLCD_print_26x32(const uint8_t c, const uint8_t offset) {
	uint8_t x=lcd_x;
	uint8_t y=lcd_y;
	GLCD_print_mem((const prog_uint8_t *)&clock_26x32[c][0][0],26,offset,0xff);
	GLCD_xy(x,y+1);
	GLCD_print_mem((const prog_uint8_t *)&clock_26x32[c][1][0],26,offset,0xff);
	GLCD_xy(x,y+2);
	GLCD_print_mem((const prog_uint8_t *)&clock_26x32[c][2][0],26,offset,0xff);
	GLCD_xy(x,y+3);
	GLCD_print_mem((const prog_uint8_t *)&clock_26x32[c][3][0],26,offset,0xff);
	GLCD_xy(x+26,y);
}
void GLCD_print_dd13x32(const uint8_t c, const uint8_t offset) {
	uint8_t x=lcd_x;
	uint8_t y=lcd_y;
	GLCD_print_mem((const prog_uint8_t *)&clock_dd[c][0][0],13,offset,0xff);
	GLCD_xy(x,y+1);
	GLCD_print_mem((const prog_uint8_t *)&clock_dd[c][1][0],13,offset,0xff);
	GLCD_xy(x,y+2);
	GLCD_print_mem((const prog_uint8_t *)&clock_dd[c][2][0],13,offset,0xff);
	GLCD_xy(x,y+3);
	GLCD_print_mem((const prog_uint8_t *)&clock_dd[c][3][0],13,offset,0xff);
	GLCD_xy(x+13,y);
}

static uint8_t n1000(const uint16_t a){
	uint16_t tmp;
	tmp=a;
	tmp%=10000;
	return tmp/1000;
}
static uint8_t n100(const uint16_t a){
	uint16_t tmp;
	tmp=a;
	tmp%=1000;
	return tmp/100;
}
static uint8_t n10(const uint16_t a){
	uint16_t tmp;
	tmp=a;
	tmp%=100;
	return tmp/10;
}
static uint8_t n1(const uint16_t a){
	uint16_t tmp;
	tmp=a;
	tmp%=10;
	return tmp;
}

void print_pressure(const uint16_t press){
	if (display_mode!=DISPLAY_PRESSURE) return;

	GLCD_xy(0,0);
	if ((hw_flags&Press_OK)==0) {
		GLCD_print_mem((const prog_uint8_t *)&hp03_err_36x16[0],36,0,0xff);
		GLCD_xy(0,1);
		GLCD_print_mem((const prog_uint8_t *)&hp03_err_36x16[1],36,0,0xff);
		return;
	}
	GLCD_print_12x16(n1000(press),0,1);
	GLCD_print_12x16(n100(press),0,1);
	GLCD_print_12x16(n10(press),0,1);
	GLCD_xy(lcd_x,lcd_y+1);
	GLCD_print_mem((const prog_uint8_t *)&font_dot2x2,2,5,0x03);
	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,0,0xff);
	if (press%10) GLCD_print_5x8(n1(press),0,0); else GLCD_print_5x8(16,0,0);
	plot_press(press);
}// print_pressure

void GLCD_print_time() {

	if (display_mode==DISPLAY_CLOCK) {print_clock();return;}
	if (display_mode==DISPLAY_MENU) {menu(0);return;}

	/*часы и минуты*/
	GLCD_xy(START_TIME,0);
	GLCD_print_5x8(n10(time.hour),TIME_OFFSET,1);
	GLCD_print_5x8(n1(time.hour),TIME_OFFSET,1);
	GLCD_print_5x8(15,TIME_OFFSET,1);
	GLCD_print_5x8(n10(time.min),TIME_OFFSET,1);
	GLCD_print_5x8(n1(time.min),TIME_OFFSET,1);
	/*секунды*/
	GLCD_print_3x5(10,TIME_OFFSET+2,1);
	GLCD_print_3x5(n10(time.sec),TIME_OFFSET+2,1);
	GLCD_print_3x5(n1(time.sec),TIME_OFFSET+2,0);
	/*дата*/
	GLCD_xy(START_TIME,1);
	GLCD_print_5x8(n10(time.day),TIME_OFFSET,1);
	GLCD_print_5x8(n1(time.day),TIME_OFFSET,1);

	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,2,TIME_OFFSET,0xff);
	GLCD_print_mem((const prog_uint8_t *)&month_15x8[time.month-1],15,TIME_OFFSET,0xff);

	/*день недели*/
	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,4,TIME_OFFSET,0xff);
	GLCD_print_mem((const prog_uint8_t *)&dayofweek[time.day_w],8,TIME_OFFSET,0xff);
}

void print_temp(const int8_t t,const uint8_t n, const hw_ret_status err) {
	int8_t tmp;
	tmp=t;

	if (display_mode==DISPLAY_CLOCK) {print_temp_clock(t,n,err);return;}
	if (display_mode!=DISPLAY_PRESSURE) return;

	if (n) GLCD_xy(START_TEMP+42,2); else GLCD_xy(START_TEMP,2);

#ifndef Term_GRAPH
	GLCD_print_mem((const prog_uint8_t *)&sensor_10x8[n][0],10,TEMP_OFFSET,0xff);
	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,3,TEMP_OFFSET,0xff);
#endif

	if (err!=SUCCESS) {
		if (err==SHORT) GLCD_print_mem((const prog_uint8_t *)&kz_12x8[0],12,TEMP_OFFSET,0xff);
		else GLCD_print_mem((const prog_uint8_t *)&obr_12x8[0],12,TEMP_OFFSET,0xff);
		GLCD_print_5x8(16,TEMP_OFFSET,1);
		return;
	}
#ifdef Term_GRAPH
	GLCD_print_mem((const prog_uint8_t *)&sensor_20x8[n][0],19,TEMP_OFFSET,0xff);
//	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,3,TEMP_OFFSET,0xff);
#endif
	if (tmp<0) {
		GLCD_print_5x8(12,TEMP_OFFSET,1);
		tmp=abs(tmp);
	}else {
		GLCD_print_5x8(10,TEMP_OFFSET,1);
	}
	if (tmp>99) tmp=99;
	if (tmp>9) GLCD_print_5x8(n10(tmp),TEMP_OFFSET,1); else GLCD_print_5x8(16,TEMP_OFFSET,1);
	GLCD_print_5x8(n1(tmp),TEMP_OFFSET,0);
	GLCD_print_5x8(16,TEMP_OFFSET,0);
	//	GLCD_print_5x8(16,TEMP_OFFSET,1);
}

static void plot_press(const uint16_t saved_press){
#define START_PLOT_X 7

	uint16_t pmin,pmax,ptmp;
	int8_t t1min=127,t1max=-127,t2min=127,t2max=-127;
	uint8_t i;
	uint32_t tmp;
	double scale;
	uint8_t p;
	uint8_t graph;
	uint16_t p12old=0;

	p=time.position;
	pmax=ram_array[p].pressure;
	pmin=pmax;
	t1max=ram_array[p].term1;
	t1min=t1max;
	t2max=ram_array[p].term2;
	t2min=t2max;

	for (i=0;i<NUM_POINT;i++) {
		if (ram_array[p].to_time>0) {
			ptmp=(ram_array[p].pressure);
			if (i<7) {p12old=ptmp;
			}
			if (ptmp>pmax) pmax=ptmp;
			if ((ptmp<pmin)&&(ptmp>5500)) pmin=ptmp;
			if (i<48) {
				if (ram_array[p].term1>t1max) t1max=ram_array[p].term1;
				if (ram_array[p].term1<t1min) t1min=ram_array[p].term1;
				if (ram_array[p].term2>t2max) t2max=ram_array[p].term2;
				if (ram_array[p].term2<t2min) t2min=ram_array[p].term2;
			}
		}
		p=p>0?p-1:NUM_POINT-1;
	}

	if ((pmax %5)>0) pmax=((pmax /5)+1)*5;
	pmin=(pmin/10)*10;
	scale=(pmax-pmin)/24.0;
	if (scale>50) scale=100;
	else if (scale>20) scale=50;
	else if (scale>10) scale=20;
	else if (scale>5) scale=10;
	else if (scale>2) scale=5;
	else if (scale>1) scale=2;
	else scale=1;

	/*Вывод графика*/
	p=time.position<(NUM_POINT-1)?time.position+1:0;
	GLCD_xy(START_PLOT_X,4);
	for (i=0;i<NUM_POINT;i++) {
		graph=0;
		if (ram_array[p].to_time>0) {
			ptmp=ram_array[p].pressure;
			tmp=(ptmp-pmin)/scale;
			if (tmp>17) graph=~(uint8_t)(0xff>>(uint8_t)(tmp-17));
		}
		if ((i%3)==0) {if ((graph!=0xe0)&&(graph!=0xf0)) graph^=0x10;}
		GLCD_put_data(graph);
		p=p<(NUM_POINT-1)?p+1:0;
	}
	GLCD_put_data(0);
	GLCD_put_data(0x55);
	GLCD_put_data(0x55);
	GLCD_put_data(0x10);
	GLCD_put_data(0x10);

	p=time.position<(NUM_POINT-1)?time.position+1:0;
	GLCD_xy(START_PLOT_X,5);
	for (i=0;i<NUM_POINT;i++) {
		graph=0;
		if (ram_array[p].to_time>0) {
			ptmp=ram_array[p].pressure;
			tmp=(ptmp-pmin)/scale;
			if (tmp>17) graph=0xff;
			else if (tmp>9) graph=~(uint8_t)(0xff>>(uint8_t)(tmp-9));
		}
		if ((i%3)==0) {if ((graph!=0x80)&&(graph!=0xc0)) graph^=0x40;}
		if ((i%6)==0) {if ((graph!=0xfe)&&(graph!=0xfc)) graph^=0x02;}
		GLCD_put_data(graph);
		p=p<(NUM_POINT-1)?p+1:0;
	}
	GLCD_put_data(0);
	GLCD_put_data(0x55);
	GLCD_put_data(0x55);
	GLCD_put_data(0x40);
	GLCD_put_data(0x40);

	p=time.position<(NUM_POINT-1)?time.position+1:0;
	GLCD_xy(START_PLOT_X,6);
	for (i=0;i<NUM_POINT;i++) {
		graph=0;
		if (ram_array[p].to_time>0) {
			ptmp=ram_array[p].pressure;
			tmp=(ptmp-pmin)/scale;
			if (tmp>9) graph=0xff;
			else if (tmp>1) graph=~(uint8_t)(0xff>>(uint8_t)(tmp-1));
		}
		if ((i%6)==0) {if ((graph!=0xf8)&&(graph!=0xf0)) graph^=0x08;}
		GLCD_put_data(graph);
		p=p<(NUM_POINT-1)?p+1:0;
	}
	GLCD_put_data(0);
	GLCD_put_data(0x55);
	GLCD_put_data(0x55);

	/*Конец вывода графика*/

	/* Вывод масштабной сетки */
	GLCD_xy(START_PLOT_X+102,4);
	GLCD_print_3x5(n1000(pmin+20*scale),2,1);
	GLCD_print_3x5(n100(pmin+20*scale),2,1);
	GLCD_print_3x5(n10(pmin+20*scale),2,0);
	GLCD_xy(START_PLOT_X+102,5);
	GLCD_print_3x5(n1000(pmin+10*scale),4,1);
	GLCD_print_3x5(n100(pmin+10*scale),4,1);
	GLCD_print_3x5(n10(pmin+10*scale),4,0);
	GLCD_xy(START_PLOT_X+102,6);
	GLCD_print_3x5(n1000(pmin),6,1);
	GLCD_print_3x5(n100(pmin),6,1);
	GLCD_print_3x5(n10(pmin),6,0);
	/* конец вывода масштабной сетки */

	/*шкала*/
	GLCD_xy(START_PLOT_X,7);
	p=time.position<(NUM_POINT-1)?time.position+1:0;
	for (i=0;i<NUM_POINT+5;i++) {
		if (i<NUM_POINT) {
			if ((p%6)==0) GLCD_put_data(7);else {
				if ((p%2)==0) GLCD_put_data(3); else GLCD_put_data(1);
			}
		}else{
			if (i==NUM_POINT) GLCD_put_data(0); else GLCD_put_data(0x1);
		}
		switch (p){
		case 1:
		case 49:
			if (i>2) {
				GLCD_xy(lcd_x-3,lcd_y);
				GLCD_print_3x5(0,3,0);
			}
			break;
		case 13:
		case 61:
			if (i>2) {
				GLCD_xy(lcd_x-3,lcd_y);
				GLCD_print_3x5(6,3,0);
			}
			break;
		case 27:
		case 75:
			if (i>6) {
				GLCD_xy(lcd_x-7,lcd_y);
				GLCD_print_3x5(1,3,1);
				GLCD_print_3x5(2,3,0);
			}
			break;
		case 39:
		case 87:
			if (i>6) {
				GLCD_xy(lcd_x-7,lcd_y);
				GLCD_print_3x5(1,3,1);
				GLCD_print_3x5(8,3,0);
			}
			break;
		default:
			break;
		}
		p=p<(NUM_POINT-1)?p+1:0;
	}
	/*конец шкалы*/
	print_delta_press(saved_press,p12old);
	print_delta_t(t1max,t1min,t2max,t2min);
}

static void print_delta_t(int8_t t1max, int8_t t1min, int8_t t2max, int8_t t2min) {

	GLCD_xy(START_TEMP,3);
	GLCD_print_3x5(15,DELTA_T_OFFSET,0);
	GLCD_print_3x5(16,DELTA_T_OFFSET,0);
	if (t1max<0) {
		GLCD_print_3x5(14,DELTA_T_OFFSET,1);
		t1max=-t1max;
	}else{
		GLCD_print_3x5(13,DELTA_T_OFFSET,1);
	}
	if (t1max>99) t1max=99;
	if (t1max>9) GLCD_print_3x5(n10(t1max),DELTA_T_OFFSET,1);
	GLCD_print_3x5(n1(t1max),DELTA_T_OFFSET,0);
	GLCD_print_3x5(19,DELTA_T_OFFSET,0);
	GLCD_print_3x5(17,DELTA_T_OFFSET,0);
	GLCD_print_3x5(18,DELTA_T_OFFSET,0);
	if (t1min<0) {
		GLCD_print_3x5(14,DELTA_T_OFFSET,1);
		t1min=abs(t1min);
	}else{
		GLCD_print_3x5(13,DELTA_T_OFFSET,1);
	}
	if (t1min>99) t1min=99;
	if (t1min>9) GLCD_print_3x5(n10(t1min),DELTA_T_OFFSET,1);
	GLCD_print_3x5(n1(t1min),DELTA_T_OFFSET,0);
	while (lcd_x<START_TEMP+47) GLCD_print_mem((const prog_uint8_t *)&font_3x5[19][0],1,DELTA_T_OFFSET,0x1f);

	GLCD_xy(START_TEMP+42,3);
	GLCD_print_3x5(15,DELTA_T_OFFSET,0);
	GLCD_print_3x5(16,DELTA_T_OFFSET,0);
	if (t2max<0) {
		GLCD_print_3x5(14,DELTA_T_OFFSET,1);
		t2max=abs(t2max);
	}else{
		GLCD_print_3x5(13,DELTA_T_OFFSET,1);
	}
	if (t2max>99) t2max=99;
	if (t2max>9) GLCD_print_3x5(n10(t2max),DELTA_T_OFFSET,1);
	GLCD_print_3x5(n1(t2max),DELTA_T_OFFSET,0);
	GLCD_print_3x5(19,DELTA_T_OFFSET,0);
	GLCD_print_3x5(17,DELTA_T_OFFSET,0);
	GLCD_print_3x5(18,DELTA_T_OFFSET,0);
	if (t2min<0) {
		GLCD_print_3x5(14,DELTA_T_OFFSET,1);
		t2min=abs(t2min);
	}else{
		GLCD_print_3x5(13,DELTA_T_OFFSET,1);
	}
	if (t2min>99) t2min=99;
	if (t2min>9) GLCD_print_3x5(n10(t2min),DELTA_T_OFFSET,1);
	GLCD_print_3x5(n1(t2min),DELTA_T_OFFSET,0);
	while (lcd_x<START_RH) GLCD_print_mem((const prog_uint8_t *)&font_3x5[19][0],1,DELTA_T_OFFSET,0x1f);
}

static void print_delta_press(const uint16_t p1,const uint16_t p2) {
	uint8_t sign_p;
	int16_t dp;

	dp=p1-p2;
	sign_p=dp<0?1:0;
	dp=abs(dp);
	if (dp>999) dp=999;
	GLCD_xy(START_DELTA_P,0);
	if (sign_p)	GLCD_print_10x16(12-((dp>4?1:0)+(dp>0?1:0)),0,0);
	else GLCD_print_10x16(12+((dp>4?1:0)+(dp>0?1:0)),0,0);
	if (dp) {
		if (sign_p) {
			GLCD_xy(START_DELTA_P+8,0);
			while (lcd_x<START_TIME) GLCD_put_data(0);
			GLCD_xy(START_DELTA_P+8,1);

		}else{
			GLCD_xy(START_DELTA_P+8,1);
			while (lcd_x<START_TIME) GLCD_put_data(0);
			GLCD_xy(START_DELTA_P+8,0);
		}
		if (dp>99) GLCD_print_5x8(n100(dp),0,1);
		if (dp>9) GLCD_print_5x8(n10(dp),0,1);
		if (dp%10) {
			GLCD_print_5x8(13,0,0);
			GLCD_print_5x8(n1(dp),0,0);
		}
		while (lcd_x<START_TIME) GLCD_put_data(0);
	}else{
		GLCD_xy(START_DELTA_P+8,0);
		while (lcd_x<START_TIME) GLCD_put_data(0);
		GLCD_xy(START_DELTA_P+8,1);
		while (lcd_x<START_TIME) GLCD_put_data(0);

	}
}

#define _print5x8(a) GLCD_print_5x8(a,0,1)
#define _print5x8_xy(x,y,c) {GLCD_xy(x,y);GLCD_print_5x8(c,0,1);}
#define _SELECT 83

void draw_date(const menu_item_t mitem){
	GLCD_xy(0,0);
	_print5x8(mitem==DAY_SELECT?_SELECT:16);
	_print5x8(21);
	_print5x8(49);
	_print5x8(67);
	_print5x8(49);
	_print5x8(16);
	_print5x8(14);
	_print5x8(53);
	_print5x8(61);
	_print5x8(52);
	_print5x8(14);

	_print5x8(mitem==DAY_EDIT?_SELECT:16);
	_print5x8(n10(time.day));
	_print5x8(n1(time.day));
	_print5x8(mitem==MONTH_EDIT?_SELECT:16);
	_print5x8(n10(time.month));
	_print5x8(n1(time.month));
	_print5x8(mitem==YEAR_EDIT?_SELECT:16);
	_print5x8(n10(time.year));
	_print5x8(n1(time.year));
	_print5x8(16);

	GLCD_xy(0,1);
	_print5x8(mitem==HOUR_SELECT?_SELECT:16);
	_print5x8(19);
	_print5x8(65);
	_print5x8(54);
	_print5x8(61);
	_print5x8(80);
	_print5x8(16);
	_print5x8(14);
	_print5x8(72);
	_print5x8(61);
	_print5x8(14);

	_print5x8(mitem==HOUR_EDIT?_SELECT:16);
	_print5x8(n10(time.hour));
	_print5x8(n1(time.hour));
	_print5x8(mitem==MINUTE_EDIT?_SELECT:16);
	_print5x8(n10(time.min));
	_print5x8(n1(time.min));
	_print5x8(16);
	GLCD_print_3x5(n10(time.sec),2,1);
	GLCD_print_3x5(n1(time.sec),2,1);
}

void draw_time_adj(const menu_item_t mitem){
	GLCD_xy(0,2);
	_print5x8(mitem==TIME_ADJ_SELECT?_SELECT:16);
	_print5x8(38);
	_print5x8(63);
	_print5x8(53);
	_print5x8(16);
	_print5x8(16);
	_print5x8(14);
	_print5x8(85);
	_print5x8(3);
	_print5x8(1);
	_print5x8(14);

	_print5x8(mitem==TIME_ADJ_EDIT?_SELECT:16);
	_print5x8((m41_control&0x20)>0?10:12);
	_print5x8(n10(m41_control&0x1f));
	_print5x8(n1(m41_control&0x1f));
}

void draw_press_adj(const menu_item_t mitem){
	GLCD_xy(0,3);
	_print5x8(mitem==PRESS_ADJ_SELECT?_SELECT:16);
	_print5x8(21);
	_print5x8(49);
	_print5x8(51);
	_print5x8(60);
	_print5x8(13);
	_print5x8(14);
	_print5x8(85);
	_print5x8(9);
	_print5x8(9);
	_print5x8(14);
	_print5x8(mitem==PRESS_ADJ_EDIT?_SELECT:16);
	_print5x8(hop03_correct<0?12:10);
	_print5x8(n100(hop03_correct));
	_print5x8(n10(hop03_correct));
	_print5x8(13);
	_print5x8(n1(hop03_correct));
}
void draw_exit(const menu_item_t mitem){
	GLCD_xy(0,7);
	_print5x8(mitem==EXIT?_SELECT:16);
	_print5x8(19);
	_print5x8(44);
	_print5x8(38);
	_print5x8(31);
	_print5x8(21);
}
void draw_lcd_txt(){
	_print5x8(32);
	_print5x8(63);
	_print5x8(53);
	_print5x8(66);
	_print5x8(51);
	_print5x8(54);
	_print5x8(67);
	_print5x8(59);
	_print5x8(49);
	_print5x8(16);

}
void draw_lcd_max(const menu_item_t mitem){
	uint8_t i;

	GLCD_xy(0,4);
	_print5x8(mitem==LED_MAX_SELECT?_SELECT:16);
	draw_lcd_txt();
	_print5x8(61);
	_print5x8(49);
	_print5x8(59);
	_print5x8(66);
	_print5x8(mitem==LED_MAX_EDIT?_SELECT:13);
	GLCD_put_data(0x7f);
	for (i=1;i<25;i++) {GLCD_put_data(led_power_max>=i?0x3e:0);}
	GLCD_put_data(0x7f);
}
void draw_lcd_min(const menu_item_t mitem){
	uint8_t i;
	GLCD_xy(0,5);
	_print5x8(mitem==LED_MIN_SELECT?_SELECT:16);
	draw_lcd_txt();
	_print5x8(61);
	_print5x8(57);
	_print5x8(62);
	_print5x8(13);
	_print5x8(mitem==LED_MIN_EDIT?_SELECT:16);
	GLCD_put_data(0x7f);
	for (i=1;i<25;i++) {GLCD_put_data(led_power_min>=i?0x3e:0);}
	GLCD_put_data(0x7f);
}
void draw_lcd_time(const menu_item_t mitem){
	GLCD_xy(0,6);
	_print5x8(mitem==LED_TIME_SELECT?_SELECT:16);
	_print5x8(24);
	_print5x8(49);
	_print5x8(53);
	_print5x8(54);
	_print5x8(65);
	_print5x8(55);
	_print5x8(59);
	_print5x8(49);
	_print5x8(16);
	_print5x8(66);
	_print5x8(54);
	_print5x8(59);
	_print5x8(13);
	_print5x8(16);
	_print5x8(mitem==LED_TIME_EDIT?_SELECT:16);
	_print5x8(n100(led_time));
	_print5x8(n10(led_time));
	_print5x8(n1(led_time));
}


void print_temp_clock(const int8_t t,const uint8_t n, const hw_ret_status err) {
	int8_t tmp;
	tmp=t;

#if HUMIDITY>0
	if (n==0) GLCD_xy(0,6); else GLCD_xy(42,6);
#else
	if (n) GLCD_xy(64,6); else GLCD_xy(0,6);
	GLCD_xy(lcd_x+10,lcd_y);
#endif
	if (err!=SUCCESS) {
		GLCD_print_12x16(11,0,1);
		GLCD_print_12x16(11,0,1);
		GLCD_print_12x16(11,0,1);
		return;
	}
	if (tmp<0) {
		GLCD_print_12x16(11,0,1);
		tmp=-tmp;
	}else {
		GLCD_print_12x16(10,0,1);
	}
	if (tmp>99) tmp=99;
	if (tmp>9) GLCD_print_12x16(n10(tmp),0,1); else GLCD_print_12x16(12,0,1);
	GLCD_print_12x16(n1(tmp),0,1);
}
void print_clock() {
	/*часы и минуты*/
	GLCD_xy(5,1);
	GLCD_print_26x32(n10(time.hour),0);
	GLCD_print_26x32(n1(time.hour),0);
	GLCD_print_dd13x32((time.sec & 1),0);
	GLCD_print_26x32(n10(time.min),0);
	GLCD_print_26x32(n1(time.min),0);

}

#if HUMIDITY>0
void print_humidity_clock(uint8_t rh, uint8_t err){
	GLCD_xy(93,6);
	if (err!=SUCCESS) {
		GLCD_print_12x16(11,0,1);
		GLCD_print_12x16(11,0,1);
		GLCD_print_12x16(11,0,1);
		return;
	}
	if (rh>9) GLCD_print_12x16(n10(rh),0,1); else GLCD_print_12x16(12,0,1);
	GLCD_print_12x16(n1(rh),0,1);
	GLCD_print_12x16(13,0,0);
}

void print_humidity(uint8_t rh, uint8_t t, uint8_t err){
	if (display_mode==DISPLAY_CLOCK) {print_humidity_clock(rh,err);return;}
	if (display_mode!=DISPLAY_PRESSURE) return;

	GLCD_xy(START_RH,2);
	GLCD_print_mem((const prog_uint8_t *)&sensor_10x8[2][0],10,RH_OFFSET,0xff);
	GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,1,TEMP_OFFSET,0xff);
	if (err!=SUCCESS) {
		GLCD_print_5x8(12,RH_OFFSET,1);
		GLCD_print_5x8(12,RH_OFFSET,1);
		GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,2,TEMP_OFFSET,0xff);
		GLCD_print_3x5(14,RH_OFFSET+2,1);
		GLCD_print_3x5(14,RH_OFFSET+2,1);
		GLCD_print_3x5(14,RH_OFFSET+2,1);
	}else{
		if (rh>9) GLCD_print_5x8(n10(rh),RH_OFFSET,1); else GLCD_print_5x8(16,RH_OFFSET,1);
		GLCD_print_5x8(n1(rh),RH_OFFSET,1);
		GLCD_print_5x8(86,RH_OFFSET,1);
		GLCD_print_mem((const prog_uint8_t *)font_5x8_sp,2,TEMP_OFFSET,0xff);
		if (t<0) {
			GLCD_print_3x5(14,RH_OFFSET+2,1);
			t=-t;
		}else{
			GLCD_print_3x5(13,RH_OFFSET+2,1);
		}
		if (t>9) {
			GLCD_print_3x5(n10(t),RH_OFFSET+2,1);
			GLCD_print_3x5(n1(t),RH_OFFSET+2,0);
		}else{
			GLCD_print_3x5(n1(t),RH_OFFSET+2,1);
			GLCD_print_3x5(19,RH_OFFSET+2,0);
		}
	}
}

#endif /* HUMIDITY */
